package serv.midser.fileserver;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import serv.utils.HttpUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 文件上传适配器
 * 
 * @author Administrator
 *
 */
public class FileServerAdapter {
	
	// 静态资源基础路径
	private String baseurl;

	// Base64上传方式
	private String base64uploadurl;

	// Form上传方式
	private String formuploadurl;
    
	// 接入代码
	private String accessid;
    
	// 私钥
	private String privatekey;
	
	
	/**
	 * 发送文件
	 * @param in
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	public String sendFile(InputStream in, String filename) throws IOException {
		return uploadFileByBase64(in, filename);
	}
	
	
	/**
	 * 发送文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public String sendFile(File file) throws IOException {
		return uploadFileByForm(file);
	}
	
	
	/**
	 * 获得基础URL地址
	 * @return
	 */
	public String getBaseurl() {
		return baseurl;
	}


	/**
	 * 转换流
	 * @param in
	 * @return
	 * @throws IOException
	 */
	private byte[] readInputStream(InputStream in) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			byte[] buffer = new byte[500];
			int size = -1;
			while ((size = in.read(buffer)) > 0) {
				out.write(buffer, 0, size);
			}
		} finally {
			out.flush();
			in.close();
		}
		return out.toByteArray();
	}
	
	/**
	 * 读取文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	private byte[] readFile(File file) throws IOException {
		FileInputStream in = new FileInputStream(file);
		return readInputStream(in);
	}
	
	/**
	 * 发送post提交
	 * @param post
	 * @return
	 * @throws HttpException
	 * @throws IOException
	 */
	private String fireHttpPost(HttpPost post) throws HttpException, IOException {
		HttpClient client = new DefaultHttpClient();
		try {
			HttpResponse response = client.execute(post);
			if (response.getStatusLine().getStatusCode() != 200) {
				throw new IOException("send file faild, error http code : " + response.getStatusLine().getStatusCode());
			}
			@SuppressWarnings("rawtypes")
			Map rs = new ObjectMapper().readValue(IOUtils.toString(response.getEntity().getContent(), "UTF-8"), Map.class);
			if (!"0000".equals(rs.get("err_code"))) {
				throw new IOException("send file faild, server exception : " + rs.get("err_msg"));
			}
			return (String) rs.get("url");
		} finally {
			post.releaseConnection();
			client.getConnectionManager().shutdown();
		}
	}
	
	/**
	 * 发送文件
	 * @param filename
	 * @param base64
	 * @return
	 * @throws HttpException
	 * @throws IOException
	 */
	private String sendFileByBase64(String filename, String base64) throws IOException {
		//
		Map<String, Object> data = new HashMap<String, Object>();
		//
		data.put("base64", base64);
		data.put("originalname", filename);
		data.put("accessid", accessid);
		String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		data.put("timestamp", timestamp);
		data.put("sign", DigestUtils.md5Hex(accessid + timestamp + privatekey));
		//
		String res = HttpUtils.post(base64uploadurl, new ObjectMapper().writeValueAsString(data));
		return res;
	}
	
	
	/**
	 * 通过form发送
	 * @param file
	 * @return
	 * @throws HttpException
	 * @throws IOException
	 */
	private String sendFileByForm(File file) throws IOException {
		String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		Map<String, File> filePart = new HashMap<String, File>();
		filePart.put("upload_file", file);
		Map<String, String> parmars = new HashMap<String, String>();
		parmars.put("accessid", accessid);
		parmars.put("timestamp", timestamp);
		parmars.put("sign", DigestUtils.md5Hex(accessid + timestamp + privatekey));
		String res = HttpUtils.post(formuploadurl, filePart, parmars);
		@SuppressWarnings("rawtypes")
		Map rs = new ObjectMapper().readValue(res, Map.class);
		if (!"0000".equals(rs.get("err_code"))) {
			throw new IOException("send file faild, server exception : " + rs.get("err_msg"));
		}
		return (String) rs.get("url");
	}
	
	
	/**
	 * 上传文件，返回URL地址
	 * @param file
	 * @return
	 * @throws IOException
	 */
	protected String uploadFileByBase64(File file) throws IOException {
		byte[] bytes = readFile(file);
		return uploadFileByBase64(bytes, file.getName());
	}
	
	/**
	 * 上传文件
	 * @param in
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	protected String uploadFileByBase64(InputStream in, String filename) throws IOException {
		byte[] bytes = readInputStream(in);
		return uploadFileByBase64(bytes, filename);
	}
	
	
	/**
	 * 上传文件
	 * @param bytes
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	protected String uploadFileByBase64(byte[] bytes, String filename) throws IOException {
		String base64 = new String(Base64.encodeBase64(bytes), "UTF-8");
		String url = sendFileByBase64(filename, base64);
		return url;
	}
	
	
	/**
	 * 上传文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	protected String uploadFileByForm(File file) throws IOException {
		return sendFileByForm(file);
	}
	
	
	/**
	 * 上传文件
	 * @param in
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	protected String uploadFileByForm(InputStream in, String filename) throws IOException {
		File temp = new File(
				"upload_tmp" 
						+ File.separator 
						+ new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + "_" + new Random().nextInt(9999) 
						+ File.separator 
						+ filename);
		temp.getParentFile().mkdirs();
		temp.createNewFile();
		FileOutputStream fos = new FileOutputStream(temp);
		try {
			byte[] buffer = new byte[500];
			int size = -1;
			while ((size = in.read(buffer)) > 0) {
				fos.write(buffer, 0, size);
			}
		} finally {
			fos.close();
			in.close();
		}
		String url = uploadFileByForm(temp);
		temp.delete();
		temp.getParentFile().deleteOnExit();
		temp.getParentFile().getParentFile().deleteOnExit();
		return url;
	}


	public String getBase64uploadurl() {
		return base64uploadurl;
	}


	public void setBase64uploadurl(String base64uploadurl) {
		this.base64uploadurl = base64uploadurl;
	}


	public String getFormuploadurl() {
		return formuploadurl;
	}


	public void setFormuploadurl(String formuploadurl) {
		this.formuploadurl = formuploadurl;
	}


	public String getAccessid() {
		return accessid;
	}


	public void setAccessid(String accessid) {
		this.accessid = accessid;
	}


	public String getPrivatekey() {
		return privatekey;
	}


	public void setPrivatekey(String privatekey) {
		this.privatekey = privatekey;
	}


	public void setBaseurl(String baseurl) {
		this.baseurl = baseurl;
	}
	
	
	

	
	
	
	
	

}
